﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace DigitalImage.softLib.stages {
    class CCTBkmeans:IColorToBinary {
        private CKMeansColor kmeans;
        private Rectangle activeZone;
        private Bitmap trainImage;

        public CCTBkmeans(Rectangle activeZone,Bitmap trainImage) {
            this.activeZone = activeZone;
            this.trainImage=trainImage;
            kmeans = new CKMeansColor();
            kmeans.brojGrupa = 2;
            train();
        }

        protected void train(){
            byte[, ,] slika = CImageUtil.bitmapToColorMatrix(trainImage);
            int xMin;
            int xMax;
            int yMin;
            int yMax;

            if (activeZone.Equals(Rectangle.Empty)) {
                xMin = yMin = 0;
                xMax = slika.GetLength(0);
                yMax = slika.GetLength(1);
            } else {
                xMin = activeZone.Location.X;
                yMin = activeZone.Location.Y;
                xMax = activeZone.Size.Width;
                yMax = activeZone.Size.Height;
            }

            Dictionary<Color, int> colorHistogram = new Dictionary<Color, int>();
            for (int y = yMin; y < yMax; y++) {
                for (int x = xMin; x < xMax; x++) {
                    byte cbR = slika[x, y, 0];
                    byte cbG = slika[x, y, 1];
                    byte cbB = slika[x, y, 2];

                    Color cc = Color.FromArgb(cbR, cbG, cbB);
                    if (colorHistogram.ContainsKey(cc)) {
                        int n = colorHistogram[cc];
                        n++;
                        colorHistogram[cc] = n;
                    } else {
                        colorHistogram.Add(cc, 1);
                    }
                }
            }

            foreach (Color key in colorHistogram.Keys) {
                kmeans.elementi.Add(key);
            }

            kmeans.podeliUGRupe(kmeans.brojGrupa, 0.05);
        }

        public byte[,] transform(Bitmap inputImage) {
            byte[, ,] slika = CImageUtil.bitmapToColorMatrix(inputImage);
            // -------- primeniti filter na sliku ----------------
            int w = slika.GetLength(0);
            int h = slika.GetLength(1);
            byte[,] nslika = new byte[w,h];

            for (int y = 0; y < h; y++) {
                for (int x = 0; x < w; x++) {
                    byte cbR = slika[x, y, 0];
                    byte cbG = slika[x, y, 1];
                    byte cbB = slika[x, y, 2];
                    Color cc = Color.FromArgb(255, cbR, cbG, cbB);

                    // za svaki piksel na slici odrediti kojem klasteru pripada
                    // pronalazenje indeksa (rednog broja) klastera kojem pripada piksel
                    int najbliza = 0;
                    for (int i = 1; i < kmeans.brojGrupa; i++) {
                        CClusterColor grupa = kmeans.grupe[i];
                        if (grupa.rastojanje(cc) < kmeans.grupe[najbliza].rastojanje(cc)) {
                            najbliza = i;
                        }
                    }
                    if (najbliza == 0) {
                        nslika[x, y] = 0;
                    } else {
                        nslika[x, y] = 255;
                    }
                }
            }
            return checkCorrectColors(nslika);
        }

        protected byte[,] checkCorrectColors(byte[,] slika) { 
            int brojBelih=0;
            int brojCrnih=0;

            for(int i=0;i<slika.GetLength(0);i++) {
                for(int j=0;j<slika.GetLength(1);j++) {
                    if(slika[i, j]==0) {
                        brojCrnih++;
                    } else {
                        brojBelih++;
                    }
                }
            }

            if(brojBelih<brojCrnih) {
                return CImageUtil.invert(slika);
            } else {
                return slika;
            }
        }
    }
}
